package com.vcredit.creditcat.service.speedloan;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;

import org.apache.commons.lang.ObjectUtils;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import com.vcredit.creditcat.dto.creditrepository.ItemStatusDto;
import com.vcredit.creditcat.dto.product.ProductApplyResultDto;
import com.vcredit.creditcat.dto.speedloan.ButtonConfigDto;
import com.vcredit.creditcat.dto.speedloan.CheckCustResultDto;
import com.vcredit.creditcat.dto.speedloan.CreditInfoDto;
import com.vcredit.creditcat.dto.speedloan.FastProduct;
import com.vcredit.creditcat.dto.speedloan.FastProductsDto;
import com.vcredit.creditcat.dto.speedloan.LoanProductsDto;
import com.vcredit.creditcat.dto.speedloan.SpeedIndexV3Dto;
import com.vcredit.creditcat.dto.speedloan.SpeedloanAuthItemDto;
import com.vcredit.creditcat.dto.speedloan.SpeedloanCanApplyProductsDto;
import com.vcredit.creditcat.dto.speedloan.SpeedloanHotProductDto;
import com.vcredit.creditcat.dto.speedloan.SpeedloanIndexDto;
import com.vcredit.creditcat.dto.speedloan.SpeedloanPrecheckDto;
import com.vcredit.creditcat.dto.speedloan.SpeedloanPrecheckItemDto;
import com.vcredit.creditcat.dto.speedloan.SpeedloanPrecheckItemV2Dto;
import com.vcredit.creditcat.dto.speedloan.SpeedloanPreviewDto;
import com.vcredit.creditcat.enumtype.AbilityEnum;
import com.vcredit.creditcat.enumtype.AssureStatusEnum;
import com.vcredit.creditcat.enumtype.AuthItemEnum;
import com.vcredit.creditcat.enumtype.ProductAuditResultEnum;
import com.vcredit.creditcat.enumtype.product.h5.AvailableProductsVo;
import com.vcredit.creditcat.exception.SpeedloanCommitException;
import com.vcredit.creditcat.model.ButtonConfig;
import com.vcredit.creditcat.model.CreditAssure;
import com.vcredit.creditcat.model.Cust;
import com.vcredit.creditcat.model.CustAbility;
import com.vcredit.creditcat.model.CustAccount;
import com.vcredit.creditcat.model.CustProductApply;
import com.vcredit.creditcat.model.CustSupplementItem;
import com.vcredit.creditcat.model.MerchantProduct;
import com.vcredit.creditcat.model.ProcessSpecial;
import com.vcredit.creditcat.model.ProcessSpecialCust;
import com.vcredit.creditcat.model.ProcessSpecialItem;
import com.vcredit.creditcat.model.ProductCheckcustItem;
import com.vcredit.creditcat.model.ProductCondition;
import com.vcredit.creditcat.model.ProductSupplementItem;
import com.vcredit.creditcat.model.RegisterChannel;
import com.vcredit.creditcat.model.TextConstant;
import com.vcredit.creditcat.model.UserTempExt;
import com.vcredit.creditcat.model.base.AbstractItem;
import com.vcredit.creditcat.service.AuthItemService;
import com.vcredit.creditcat.service.CreditAssureService;
import com.vcredit.creditcat.service.CustAbilityService;
import com.vcredit.creditcat.service.CustAccountService;
import com.vcredit.creditcat.service.CustCreditRepositoryService;
import com.vcredit.creditcat.service.CustProductApplyService;
import com.vcredit.creditcat.service.CustSupplementItemService;
import com.vcredit.creditcat.service.MerchantProductService;
import com.vcredit.creditcat.service.ProductCheckcustItemService;
import com.vcredit.creditcat.service.ProductConditionService;
import com.vcredit.creditcat.service.UserTempService;
import com.vcredit.creditcat.service.auth.AuthItemExtService;
import com.vcredit.creditcat.service.product.CreditProductService;
import com.vcredit.creditcat.util.ConcurrentDateUtil;
import com.vcredit.creditcat.util.EnumExtUtil;
import com.vcredit.creditcat.util.Utility;
import com.vcredit.creditcat.vo.ProductApplyResultVo;
import com.vcredit.creditcat.vo.auth.supplement.CustSupplementItemExt;
import com.vcredit.creditcat.vo.product.ButtonConfigLists;
import com.vcredit.framework.annotation.Log;
import com.vcredit.framework.util.BeanUtil;
import com.vcredit.framework.util.JacksonUtil;

@Service
public class SpeedloanService extends ProductCheckCustServiceAdaptor {

	private static List<Integer> creditPhaseForCheckUser; // 用于校验交单规则的授信阶段

	private static Map<Integer, String> speedloanItemTitles; // 快贷产品文案提示

	static {
		creditPhaseForCheckUser = new ArrayList<Integer>();
		creditPhaseForCheckUser.add(0); // 认证项申请中
		creditPhaseForCheckUser.add(1); // 认证项失败
		creditPhaseForCheckUser.add(5); // 有可申请的产品
		creditPhaseForCheckUser.add(6); // 认证项未做

		speedloanItemTitles = new HashMap<Integer, String>();
		speedloanItemTitles.put(0, "完成如下步骤可申请");
		speedloanItemTitles.put(1, "部分认证未成功");
		speedloanItemTitles.put(2, "额度审批中");
		speedloanItemTitles.put(3, "额度审批成功");
		speedloanItemTitles.put(4, "额度审批失败,{date}可重新申请");
		speedloanItemTitles.put(5, "认证项已完成，请提交产品");
		speedloanItemTitles.put(6, "完成如下步骤可申请");
		speedloanItemTitles.put(7, "额度审批失败，可申请挽回");
	}

	private static final String DATE_REGEX = "{date}";
	private static final String AMT_REGEX = "{amt}";
	private static final String PRODUCT_REMARK = "贷款成功返{amt}元";

	@Value("${product.detail.url}")
	private String productDetailUrl;

	@Value("${product.tixian.h5}")
	private String tixian;

	@Value("${product.tixian.xinyonghua.h5}")
	private String xinyonghua;

	@Autowired
	private AuthItemExtService authItemExtService;
	@Autowired
	private CustCreditRepositoryService creditRepositoryService;
	@Autowired
	private ProcessSpecialService processSpecialService;
	@Autowired
	private ProcessSpecialItemService processSpecialItemService;
	@Autowired
	private AuthItemService authItemService;
	@Autowired
	private MerchantProductService merchantProductService;
	@Autowired
	private CreditProductService creditProductService;
	@Autowired
	private CustProductApplyService custProductApplyService;
	@Autowired
	private ProcessSpecialCustService processSpecialCustService;
	@Autowired
	private CustSupplementItemService custSupplementItemService;
	@Autowired
	private ProductCheckcustItemService productCheckcustItemService;
	@Autowired
	private CustCreditRepositoryService custCreditRepositoryService;
	@Autowired
	private CreditAssureService creditAssureService;
	@Autowired
	private CustAccountService custAccountService;
	@Autowired
	private ProductConditionService productConditionService;
	@Autowired
	private UserTempService userTempService;
	@Autowired
	private CustAbilityService custAbilityService;
	private static final Logger LOG = LoggerFactory.getLogger(ProductCheckCustServiceAdaptor.class);

	/**
	 * 封装 授信信息 返回 chengxin
	 *
	 * @param creditInfo
	 * @param cust
	 * @return
	 * @throws Exception
	 */
	public CreditInfoDto creditInfoDtoReturn(CreditInfoDto creditInfo, Cust cust, String appDesc, int status, List<CustProductApply> productApplyList, List<ProcessSpecial> processSpecials) throws Exception {

		// 还一种情况是 之前申请过产品，但是有产品正在申请中 或者申请成功 ，则优先展示这些
		int applying = 0;// 申请中的产品
		int applySuccess = 0;// 申请成功的产品
		int creditAmt = 0;// 申请的总产品
		StringBuffer sub = new StringBuffer();
		for (ProcessSpecial processSpecial : processSpecials) {
			sub.append(processSpecial.getProductId() + ";");
		}
		/*
		 * 审核结果 0：已审批-失败；1：已审批-成功；2：审批中；3：未申请过；4：未申请过，认证条件齐全； 5：额度获取失败临时状态;
		 * 7：授信失败，可挽回； 22：快贷流程提交中
		 */
		// 有申请产品
		if (productApplyList.size() > 0) {
			for (CustProductApply custProductApply : productApplyList) {
				if (sub.toString().contains(custProductApply.getProductId()+"")) {
					int appproduct = custProductApply.getAuditResult();
					if (2 == custProductApply.getAuditResult() || 22 == custProductApply.getAuditResult()) {
						applying++;
					}
					if (0 == appproduct || 1 == appproduct || 8 == appproduct || 9 == appproduct || 10 == appproduct || 11 == appproduct || 12 == appproduct || 13 == appproduct) {
						applySuccess++;
						creditAmt += custProductApply.getCreditAmt();
					}
				}
			}
			if (applySuccess > 0) {
				creditInfo.setCreditPhase(TextConstant.APPLYEDSTATUS); // 授信阶段（（1:未申请2.未申请，产品待提交10:额度审批中20:至少有一款产品已出授信结果30.认证项已过期
				creditInfo.setCreditLimit(creditAmt / 100 + ".00"); // string
				creditInfo.setPromptMsg(""); // 累计授信额度
				creditInfo.setPromoteUrl(""); // string 提额链接，有则开放提额按钮，无则置灰
			}
			if (applying > 0) {
				creditInfo.setPromptMsg(TextConstant.applying); // string
				if (applySuccess > 0) {

					creditInfo.setPromptMsg(TextConstant.HAVE + applying + TextConstant.hasApplying); // 提示文案
				} else {
					creditInfo.setCreditPhase(TextConstant.APPLYINGSTATUS);
				}
			}
			// 如果是都是失败的。并且认证项已经做过
			if (0 == applying && 0 == applySuccess) {
				// 认证项全过
				if (0 == status) {
					creditInfo.setCreditPhase(TextConstant.NOAPPLYSTATUS); // 授信阶段（（1:未申请2.未申请，产品待提交10:额度审批中20:至少有一款产品已出授信结果30.认证项已过期
					creditInfo.setPromptMsg(TextConstant.clickMoney); // string
																		// 提示文案
					creditInfo.setPromoteUrl(""); // string 提额链接，有则开放提额按钮，无则置灰
				} else if (5 == status) {
					creditInfo.setCreditPhase(TextConstant.CANAPPLYSTATUS); // 授信阶段（（1:未申请
					// 2.未申请，产品待提交10:额度审批中20:至少有一款产品已出授信结果
					creditInfo.setPromptMsg(TextConstant.MONEY); // string 提示文案
					creditInfo.setPromoteUrl(TextConstant.JUMPURL); // string
																	// 提额链接，有则开放提额按钮，无则置灰
				} else if (6 == status) {
					creditInfo.setCreditPhase(TextConstant.APPLYEDSTATUS); // 授信阶段（（1:未申请
					// 2.未申请，产品待提交10:额度审批中20:至少有一款产品已出授信结果
					creditInfo.setPromptMsg(TextConstant.ZEROMONEY); // string
																		// 提示文案
					creditInfo.setPromoteUrl(TextConstant.JUMPURL); // string
				} else if (7 == status) {
					creditInfo.setCreditPhase(TextConstant.AUTHExeTimeSTATUS); //
					creditInfo.setPromoteUrl(TextConstant.JUMPURL);
					creditInfo.setPromptMsg(TextConstant.FAILAUTH); // string 提示
				}
			}
		} else {
			// 没有申请产品 （0:申请中, 5:有可申请的产品,6:已完成）
			// 认证项全过

			if (5 == status) {
				creditInfo.setCreditPhase(TextConstant.CANAPPLYSTATUS); // 授信阶段（（1:未申请
				// 2.未申请，产品待提交10:额度审批中20:至少有一款产品已出授信结果
				creditInfo.setPromptMsg(TextConstant.MONEY); // string 提示文案
				creditInfo.setPromoteUrl(TextConstant.JUMPURL); // string
																// 提额链接，有则开放提额按钮，无则置灰
			} else if (0 == status) {
				creditInfo.setCreditPhase(TextConstant.NOAPPLYSTATUS); //
				creditInfo.setPromptMsg(TextConstant.clickMoney); // ; // string
																	// 提示
				creditInfo.setPromoteUrl(TextConstant.JUMPURL); // string
			} else if (6 == status) {
				creditInfo.setCreditPhase(TextConstant.CANAPPLYSTATUS); //
				creditInfo.setPromoteUrl("");
				creditInfo.setPromptMsg(""); // string 提示
			} else if (7 == status) {
				creditInfo.setCreditPhase(TextConstant.AUTHExeTimeSTATUS); //
				creditInfo.setPromoteUrl(TextConstant.JUMPURL);
				creditInfo.setPromptMsg(TextConstant.FAILAUTH); // string 提示
			}
		}

		return creditInfo;

	}

	/**
	 * 快贷产品列表 按钮配置 chengxin
	 *
	 * @param speedIndexV3Dto
	 * @param accessToken
	 * @param cust
	 * @param appDesc
	 * @param pageIndex
	 * @param pageSize
	 * @return
	 * @throws Exception
	 */
	public SpeedIndexV3Dto fastProductsReturn(SpeedIndexV3Dto speedIndexV3Dto, String accessToken, Cust cust, String appDesc, int pageIndex, int pageSize, boolean fastFlag, boolean loanFlag, int status,
			List<CustProductApply> productApplyList, String mobile, List<ProcessSpecial> processSpecials) throws Exception {
		StringBuffer buffer = new StringBuffer();

		if (productApplyList.size() > 0) {
			for (CustProductApply custapp : productApplyList) {
				buffer.append(custapp.getProductId() + ";");
			}
		}
		// 快贷产品列表 按钮配置
		List<FastProductsDto> fastProductsList = new ArrayList<FastProductsDto>();// 快贷产品列表（显示所有已获得授信结果的贷款产品）

		// 贷款产品列表
		List<LoanProductsDto> loanProducts = new ArrayList<LoanProductsDto>();// 贷款产品列表（默认显示20条）
		LoanProductsDto loanProductsDto = new LoanProductsDto();

		int start = 0;
		int end = 0;
		if (pageIndex != 0) {
			start = pageIndex * pageSize;
		}
		end = start + pageSize;

		List<MerchantProduct> hotProducts = this.getHotProducts(appDesc, cust.getCustId());

		if (Utility.isNullOrEmpty(processSpecials)) {
			// 默认展示信用花
			ProcessSpecial processSpecial = processSpecialService.findByProductId(6L);
			if (null != processSpecial) {
				processSpecials = new ArrayList<ProcessSpecial>();
				processSpecials.add(processSpecial);
			}
		}
		List<Map<String, Long>> paginationList = this.getPaginationLists(cust, null, processSpecials, hotProducts);

		Map<Long, MerchantProduct> allMerchantProduct = merchantProductService.findAll();

		List<ButtonConfig> buttonConfigList = ButtonConfigLists.buttonConfigList;

		for (Map<String, Long> map : paginationList) {
			Long pId = map.get("productId");
			// 判断是否需要展示
			if (map.get("type") == 1 && fastFlag) { // 快贷产品
				SpeedloanPrecheckItemV2Dto sp = this.getPrecheckItemV2(cust, allMerchantProduct.get(pId.longValue()));
				if (StringUtils.isNotBlank(sp.getProductName())) {
					// FastProductsDto vo = getPrecheckItemV3(cust,
					// allMerchantProduct.get(pId.longValue()),
					// buttonConfigList, status, buffer);
					if (null != cust.getCustId()) {
						FastProductsDto vo = getPrecheckItemV3New(cust, allMerchantProduct.get(pId.longValue()), buttonConfigList, productApplyList);
						if (null != vo) {
							fastProductsList.add(vo);
						}
					}

				}
			} else { // 热门贷款
				if (loanFlag) {
					SpeedloanHotProductDto sp = this.getHotProductDto(cust, accessToken, allMerchantProduct.get(pId.longValue()));
					if (null != sp.getProductId()) {
						loanProductsDto = new LoanProductsDto();
						loanProducts.add(loanProductsDto(loanProductsDto, sp));
					}
				}
			}
		}

		if (start >= paginationList.size()) {
			loanProducts = new ArrayList<LoanProductsDto>();
			speedIndexV3Dto.setLoanProducts(loanProducts);
		} else {
			if (end <= loanProducts.size()) {
				loanProducts = loanProducts.subList(start, end);
			} else {
				loanProducts = loanProducts.subList(start, loanProducts.size());
			}
			speedIndexV3Dto.setLoanProducts(loanProducts);
		}
		speedIndexV3Dto.setFastProducts(fastProductsList);

		return speedIndexV3Dto;
	}

	/**
	 * 封装快贷产品数据项
	 * 
	 * @author chengxin
	 * @param cust
	 * @param merchantProduct
	 * @return
	 * @throws Exception
	 */
	@SuppressWarnings("unused")
	private FastProductsDto getPrecheckItemV3New(Cust cust, MerchantProduct merchantProduct, List<ButtonConfig> buttonConfigList, List<CustProductApply> productApplyList) throws Exception {
		FastProductsDto fastProducts = new FastProductsDto();
		Map<String, Object> precheckResult = this.precheck(merchantProduct.getProductId(), cust, false);
		SpeedloanPrecheckItemDto precheckItemDto = (SpeedloanPrecheckItemDto) precheckResult.get("precheckItemDto");
		int status = precheckItemDto.getCreditPhase();// 授信阶段（0、认证中 ;1、认证失败 ;
														// 2、额度审批中; 3、授信成功;
														// 4、授信失败;
		long productId = precheckItemDto.getProductId();
		// 5、有可申请的产品, 6、未申请 7：授信失败，可挽回 8:授信后,放款 拼接button 拼接产品显示
		// 只有 2,3,4,5,8 可进入
		// 只显示 出结果的产品

		if (productApplyList.size() > 0) {
			for (CustProductApply custPro : productApplyList) {
				if (productId == custPro.getProductId()) {
					// 是否可以再申请
					boolean canProductApplyAgin = custProductApplyService.canProductApplyAgin(custPro);

					ButtonConfigDto buttonConfigDto = new ButtonConfigDto();
					int resultStatus = custPro.getAuditResult();
					boolean isApply = custPro.getIsApply();
					// 拼接额度、费率
					StringBuilder sb = new StringBuilder();
					sb.append(TextConstant.E_DU).append(precheckItemDto.getLimitRange()).append(TextConstant.KONG_GE).append(TextConstant.SHU_GANG).append(TextConstant.KONG_GE).append(TextConstant.FEI_LV)
							.append(precheckItemDto.getMonthlyRate());

					String productDesc = sb.toString();
					sb.delete(0, sb.length());

					// 拼接XXX人成功申请
					sb.append(merchantProduct.getProductApplycount()).append(TextConstant.CHENG_GONG_SHEN_QING);
					fastProducts.setProductId(productId);// long
															// 产品编号
					fastProducts.setProductIcon(precheckItemDto.getProductIcon());// string
																					// 产品图标
					fastProducts.setProductName(precheckItemDto.getProductName());// string
					fastProducts.setCreditLimit(precheckItemDto.getLimitRange() + "");// string
					SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
					SimpleDateFormat dfs = new SimpleDateFormat("yyyy-MM-dd");

					buttonConfigDto = buttonConfigParam(buttonConfigDto, precheckItemDto, buttonConfigList);

					// button 配置 1.存在额度 额度值必须有

					fastProducts.setPhaseDesc(precheckItemDto.getCreditDesc());// string

					// fastProducts.setButtonConfig(buttonConfigDto);
					fastProducts.setButtonConfig(null);// 阶段描述
					String productDescs = merchantProduct.getTag();
					if (productDesc.split(",").length > 2) {
						String[] descArr = productDescs.split(",");
						sb.append(descArr[0].trim()).append(TextConstant.DOU_HAO).append(descArr[1].trim());
						productDescs = sb.toString();
					}
					fastProducts.setProductLabel(productDescs);// string 产品标签
					fastProducts.setSalesModel(precheckItemDto.getSalesModel());
					String formatDate = df.format(precheckItemDto.getExpiryTime()); //
					// 0：已审批-失败；1：已审批-成功；2：审批中；3：未申请过；4：未申请过，认证条件齐全；5：额度获取失败临时状态;
					// 7：授信失败，可挽回；8：放款审核中；9：放款审核未通过；10：放款审核通过；11：还款中；12：还款逾期中；13：已结清；22：快贷流程提交中
					switch (resultStatus) {
					case 0:
						if (canProductApplyAgin) {
							buttonConfigDto = new ButtonConfigDto(TextConstant.AUTHFAILD, "1", TextConstant.JUMPURL);
						} else {
							buttonConfigDto = new ButtonConfigDto(TextConstant.AUTHFAILD, "-1", TextConstant.JUMPURL);
						}
						if (isApply) {
							if (StringUtils.isNotBlank(precheckItemDto.getFrozenTime())) {
								int buttonDay = ConcurrentDateUtil.daysBetween(ConcurrentDateUtil.formatDateTime(new Date()), precheckItemDto.getFrozenTime());
								if (buttonDay > 0) {
									Date datetime = dfs.parse(precheckItemDto.getFrozenTime());
									String times = dfs.format(datetime);
									fastProducts.setPhaseDesc(TextConstant.AUTHFOUR + "," + times + TextConstant.AUTHFOURREFUSE);//
								} else {
									fastProducts.setPhaseDesc(TextConstant.AUTHSIX);//
								}
							} else {
								fastProducts.setPhaseDesc(TextConstant.AUTHFOUR);// 过期描述，例如:5天后过期、额度已过期等等
							}
							fastProducts.setCreditLimit("");
						} else {
							fastProducts.setPhaseDesc(TextConstant.PRODUCTCANNOTAPPLYING);//
							fastProducts.setCreditLimit("");
						}
						fastProducts.setButtonConfig(buttonConfigDto);
						break;

					case 7:
						if (canProductApplyAgin) {
							buttonConfigDto = new ButtonConfigDto(TextConstant.AUTHFAILD, "1", TextConstant.JUMPURL);
						} else {
							buttonConfigDto = new ButtonConfigDto(TextConstant.AUTHFAILD, "-1", TextConstant.JUMPURL);
						}
						if (StringUtils.isNotBlank(precheckItemDto.getFrozenTime())) {
							int buttonDay = ConcurrentDateUtil.daysBetween(ConcurrentDateUtil.formatDateTime(new Date()), precheckItemDto.getFrozenTime());
							Date datetime = dfs.parse(precheckItemDto.getFrozenTime());
							String times = dfs.format(datetime);
							fastProducts.setPhaseDesc(TextConstant.AUTHFOUR + "," + times + TextConstant.AUTHFOURREFUSE);//
						} else {
							fastProducts.setPhaseDesc(TextConstant.AUTHFOUR);// 过期描述，例如:5天后过期、额度已过期等等
						}
						fastProducts.setCreditLimit("");
						fastProducts.setButtonConfig(buttonConfigDto);
						break;
					case 8:
					case 9:
					case 10:
					case 11:
					case 12:
					case 13:
						/*
						 * fastProducts.setPhaseDesc(TextConstant.AUTHTHREE);//
						 * string // 是否过期 int dayss =
						 * ConcurrentDateUtil.daysBetween(ConcurrentDateUtil.
						 * formatDateTime(new Date()), formatDate); if (dayss >=
						 * 0) { if (buttonConfigList.size() > 0) {
						 * buttonConfigDto = new
						 * ButtonConfigDto(TextConstant.TIXIAN, "-1", tixian);
						 * fastProducts.setCountdown(dayss +
						 * TextConstant.OVERDUE);// 过期描述，例如:5天后过期、额度已过期等等
						 * fastProducts.setPhaseDesc("");
						 * fastProducts.setProductDesc("");// string 产品描述 } }
						 * else { if (canProductApplyAgin) { buttonConfigDto =
						 * new ButtonConfigDto(TextConstant.AUTHFAILD, "1",
						 * TextConstant.JUMPURL); } else { buttonConfigDto = new
						 * ButtonConfigDto(TextConstant.AUTHFAILD, "-1",
						 * TextConstant.JUMPURL); }
						 * fastProducts.setCountdown(TextConstant.OVERDUED);//
						 * 过期描述，例如:5天后过期、额度已过期等等 }
						 * 
						 * fastProducts.setButtonConfig(buttonConfigDto);
						 * fastProducts.setPhaseDesc("");
						 * fastProducts.setProductDesc("");// string 产品描述 int
						 * moneys = precheckItemDto.getGetLimit() / 100;
						 * fastProducts.setCreditLimit(moneys + ".00 元"); break;
						 */
					case 1:
						fastProducts.setPhaseDesc(TextConstant.AUTHTHREE);// string
						// 是否过期
						int days = ConcurrentDateUtil.daysBetween(ConcurrentDateUtil.formatDateTime(new Date()), formatDate);
						if (days >= 0) {
							if (buttonConfigList.size() > 0) {
								buttonConfigDto = new ButtonConfigDto(TextConstant.TIXIAN, "1", tixian);
								fastProducts.setCountdown(days + TextConstant.OVERDUE);// 过期描述，例如:5天后过期、额度已过期等等
								fastProducts.setPhaseDesc("");
								fastProducts.setProductDesc("");// string 产品描述
							}
						} else {
							if (canProductApplyAgin) {
								buttonConfigDto = new ButtonConfigDto(TextConstant.AUTHFAILD, "1", TextConstant.JUMPURL);
							} else {
								buttonConfigDto = new ButtonConfigDto(TextConstant.AUTHFAILD, "-1", TextConstant.JUMPURL);
							}
							fastProducts.setCountdown(TextConstant.OVERDUED);// 过期描述，例如:5天后过期、额度已过期等等
						}

						fastProducts.setButtonConfig(buttonConfigDto);
						fastProducts.setPhaseDesc("");
						fastProducts.setProductDesc("");// string 产品描述
						int money = precheckItemDto.getGetLimit() / 100;
						fastProducts.setCreditLimit(money + ".00 元");
					}
					fastProducts.setProductDesc(productDesc);// string 产品描述
					if (null == fastProducts.getButtonConfig()) {
						fastProducts.setButtonConfig(null);
					}
					break;
				}
			}
		} else {
			fastProducts = null;
		}
		if (null == fastProducts) {
			fastProducts = null;
		} else {
			if (0L == fastProducts.getProductId()) {
				fastProducts = null;
			}
		}
		return fastProducts;
	}

	/**
	 * 封装快贷产品数据项
	 * 
	 * @author chengxin
	 * @param cust
	 * @param merchantProduct
	 * @return
	 * @throws Exception
	 */
	private FastProductsDto getPrecheckItemV3(Cust cust, MerchantProduct merchantProduct, List<ButtonConfig> buttonConfigList, int buttonstatus, StringBuffer buffer) throws Exception {
		FastProductsDto fastProducts = new FastProductsDto();
		Map<String, Object> precheckResult = this.precheck(merchantProduct.getProductId(), cust, false);
		SpeedloanPrecheckItemDto precheckItemDto = (SpeedloanPrecheckItemDto) precheckResult.get("precheckItemDto");
		int status = precheckItemDto.getCreditPhase();// 授信阶段（0、认证中 ;1、认证失败 ;
														// 2、额度审批中; 3、授信成功;
														// 4、授信失败;
		long productId = precheckItemDto.getProductId();
		// 5、有可申请的产品, 6、未申请 7：授信失败，可挽回 8:授信后,放款 拼接button 拼接产品显示
		// 只有 2,3,4,5,8 可进入
		// 只显示 出结果的产品
		if (2 == status || 3 == status || 4 == status || 8 == status || buffer.toString().contains(productId + "")) {

			ButtonConfigDto buttonConfigDto = new ButtonConfigDto();

			// 拼接额度、费率
			StringBuilder sb = new StringBuilder();
			sb.append(TextConstant.E_DU).append(precheckItemDto.getLimitRange()).append(TextConstant.KONG_GE).append(TextConstant.SHU_GANG).append(TextConstant.KONG_GE).append(TextConstant.FEI_LV)
					.append(precheckItemDto.getMonthlyRate());

			String productDesc = sb.toString();
			sb.delete(0, sb.length());

			// 拼接XXX人成功申请
			sb.append(merchantProduct.getProductApplycount()).append(TextConstant.CHENG_GONG_SHEN_QING);
			fastProducts.setProductId(precheckItemDto.getProductId());// long
																		// 产品编号
			fastProducts.setProductIcon(precheckItemDto.getProductIcon());// string
																			// 产品图标
			fastProducts.setProductName(precheckItemDto.getProductName());// string
			fastProducts.setCreditLimit(precheckItemDto.getLimitRange() + "");// string
			SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
			SimpleDateFormat dfs = new SimpleDateFormat("yyyy-MM-dd");

			buttonConfigDto = buttonConfigParam(buttonConfigDto, precheckItemDto, buttonConfigList);

			// button 配置 1.存在额度 额度值必须有

			fastProducts.setPhaseDesc(precheckItemDto.getCreditDesc());// string

			// fastProducts.setButtonConfig(buttonConfigDto);
			fastProducts.setButtonConfig(null);// 阶段描述
			String productDescs = merchantProduct.getTag();
			if (productDesc.split(",").length > 2) {
				String[] descArr = productDescs.split(",");
				sb.append(descArr[0].trim()).append(TextConstant.DOU_HAO).append(descArr[1].trim());
				productDescs = sb.toString();
			}
			fastProducts.setProductLabel(productDescs);// string 产品标签
			fastProducts.setSalesModel(precheckItemDto.getSalesModel());
			String formatDate = df.format(precheckItemDto.getExpiryTime()); //
			// 显示不同的按钮状态和描述
			boolean flag = true;
			if (status == 0 && buffer.toString().contains(productId + "")) {
				status = 4;
				flag = false;
			}
			switch (status) {
			case 0:
				fastProducts.setPhaseDesc(TextConstant.RENZHENGING);// string
				break;
			case 1:
				fastProducts.setPhaseDesc(TextConstant.AUTHONE);// string
				break;
			case 2:
				fastProducts.setPhaseDesc(TextConstant.AUTHTWO);// string
				break;
			case 3:
				fastProducts.setPhaseDesc(TextConstant.AUTHTHREE);// string
				// 是否过期
				int days = ConcurrentDateUtil.daysBetween(ConcurrentDateUtil.formatDateTime(new Date()), formatDate);
				if (days > 0) {
					if (buttonConfigList.size() > 0) {
						fastProducts.setCountdown(days + TextConstant.OVERDUE);// 过期描述，例如:5天后过期、额度已过期等等
						fastProducts.setPhaseDesc("");
						fastProducts.setProductDesc("");// string 产品描述
					}
				} else {
					if (StringUtils.isNotBlank(precheckItemDto.getFrozenTime())) {

						int buttonDay = ConcurrentDateUtil.daysBetween(ConcurrentDateUtil.formatDateTime(new Date()), precheckItemDto.getFrozenTime());
						if (buttonDay > 0) {
							buttonConfigDto = new ButtonConfigDto(TextConstant.AUTHFAILD, "1", "");
							fastProducts.setButtonConfig(buttonConfigDto);
						} else {
							buttonConfigDto = new ButtonConfigDto(TextConstant.AUTHFAILD, "-1", "");
							fastProducts.setButtonConfig(buttonConfigDto);

						}
						Date data = null;
						data = dfs.parse(precheckItemDto.getFrozenTime());
						String tims = dfs.format(data);
						fastProducts.setCountdown(TextConstant.OVERDUED + tims + TextConstant.AUTHFOURREFUSE);// 过期描述，例如:5天后过期、额度已过期等等
					}
				}
				fastProducts.setButtonConfig(buttonConfigDto);
				fastProducts.setPhaseDesc("");
				fastProducts.setProductDesc("");// string 产品描述
				int money = precheckItemDto.getGetLimit() / 100;
				fastProducts.setCreditLimit(money + ".00 元");
				break;
			case 4:
				if (StringUtils.isNotBlank(precheckItemDto.getFrozenTime())) {
					int buttonDay = ConcurrentDateUtil.daysBetween(ConcurrentDateUtil.formatDateTime(new Date()), precheckItemDto.getFrozenTime());
					if (buttonDay > 0) {
						buttonConfigDto = new ButtonConfigDto(TextConstant.AUTHFAILD, "-1", TextConstant.JUMPURL);
						fastProducts.setButtonConfig(buttonConfigDto);
					} else {
						buttonConfigDto = new ButtonConfigDto(TextConstant.AUTHFAILD, "1", TextConstant.JUMPURL);
						fastProducts.setButtonConfig(buttonConfigDto);
					}
					Date datetime = dfs.parse(precheckItemDto.getFrozenTime());
					String times = dfs.format(datetime);
					fastProducts.setPhaseDesc(TextConstant.AUTHFOUR + "," + times + TextConstant.AUTHFOURREFUSE);//
				} else {
					buttonConfigDto = new ButtonConfigDto(TextConstant.AUTHFAILD, "-1", TextConstant.JUMPURL);
					fastProducts.setPhaseDesc(TextConstant.AUTHFOUR);// 过期描述，例如:5天后过期、额度已过期等等
				}
				fastProducts.setCreditLimit("");
				fastProducts.setButtonConfig(buttonConfigDto);
				break;
			case 5:
				fastProducts.setPhaseDesc(TextConstant.AUTHFIVE);// string
				break;
			case 6:
				fastProducts.setPhaseDesc(TextConstant.AUTHSIX);// string
				break;
			case 7:
				fastProducts.setPhaseDesc(TextConstant.AUTHSEVEN);// string
				break;
			case 8:
				fastProducts.setPhaseDesc(TextConstant.AUTHTHREE);// string
				// 是否过期
				days = ConcurrentDateUtil.daysBetween(ConcurrentDateUtil.formatDateTime(new Date()), formatDate);

				if (days >= 0) {
					if (buttonConfigList.size() > 0) {
						buttonConfigDto = new ButtonConfigDto(TextConstant.TIXIAN, "1", tixian);

						fastProducts.setCountdown(days + TextConstant.OVERDUE);// 过期描述，例如:5天后过期、额度已过期等等
						fastProducts.setPhaseDesc("");
						fastProducts.setProductDesc("");// string 产品描述
					}
				} else {

					buttonConfigDto = new ButtonConfigDto(TextConstant.AUTHFAILD, "-1", "");
					fastProducts.setButtonConfig(buttonConfigDto);
					fastProducts.setCountdown(TextConstant.OVERDUED);// 过期描述，例如:5天后过期、额度已过期等等
				}

				fastProducts.setButtonConfig(buttonConfigDto);
				fastProducts.setPhaseDesc("");
				fastProducts.setProductDesc("");// string 产品描述
				money = precheckItemDto.getGetLimit() / 100;
				fastProducts.setCreditLimit(money + ".00 元");
				break;
			default:
				break;
			}
			fastProducts.setProductDesc(productDesc);// string 产品描述
			if (null == fastProducts.getButtonConfig()) {
				fastProducts.setButtonConfig(null);
			}

			// 特殊产品跳转链接
			if (6L == productId && flag) {
				buttonConfigDto.setJumpUrl(xinyonghua);
				fastProducts.setButtonConfig(buttonConfigDto);
			}
		} else {
			fastProducts = null;
		}
		return fastProducts;
	}

	/**
	 * button修改
	 *
	 * @param buttonConfigDto
	 * @param precheckItemDto
	 * @param buttonConfigList
	 * @return
	 */
	public ButtonConfigDto buttonConfigParam(ButtonConfigDto buttonConfigDto, SpeedloanPrecheckItemDto precheckItemDto, List<ButtonConfig> buttonConfigList) {
		if (buttonConfigList.size() > 0) {
			for (ButtonConfig buttonConfig : buttonConfigList) {
				if (buttonConfig.getAuthStatus().equals(precheckItemDto.getCreditPhase() + "")) {
					int status = -1;
					if (null != AvailableProductsVo.getAuditResultById(precheckItemDto.getProductId())) {
						status = 1;
					}
					buttonConfigDto = new ButtonConfigDto(buttonConfig.getText(), status + "", buttonConfig.getJumpurl());
					break;
				}
			}
		}
		return buttonConfigDto;

	}

	/**
	 * 贷款列表 返回
	 * 
	 * @param sp
	 * @return
	 * @throws Exception
	 */
	public LoanProductsDto loanProductsDto(LoanProductsDto loanProductsDto, SpeedloanHotProductDto sp) throws Exception {

		loanProductsDto.setProductId(sp.getProductId());// long 产品编号
		loanProductsDto.setProductName(sp.getProductName());// string 产品名称
		loanProductsDto.setProductIcon(sp.getProductIcon());// string 产品图标
		loanProductsDto.setCreditLimit(sp.getProductAmt());// string 额度范围
		loanProductsDto.setProductDesc(sp.getProductRate());// string 产品描述
		loanProductsDto.setProductLabel(sp.getProductLabel());// string 产品标签
		loanProductsDto.setFeatureTag(sp.getFeatureTag());// string 个性标签
		loanProductsDto.setProductRemark(sp.getProductRemark());// string 产品描述
		loanProductsDto.setStatisticalDesc(sp.getProductApplyCount());// string统计描述
		loanProductsDto.setJumpUrl(sp.getJumpUrl());// string 跳转网址
		return loanProductsDto;
	}

	/**
	 * 快贷首页3.0
	 *
	 * @author zhaoqi01 存在问题 1.认证项问题 2.存在过期选项
	 * @author chengxin
	 * @param cust
	 * @return
	 * @throws Exception
	 */
	@Log
	public SpeedIndexV3Dto indexV3(Cust cust, String refreshFields, String accessToken, String appDesc, int pageIndex, int pageSize) throws Exception {
		SpeedIndexV3Dto results = new SpeedIndexV3Dto();
		// 授信信息1.授信阶段（0:申请中, 5:有可申请的产品,6:已完成7.有认证项失败）
		SpeedloanPreviewDto dot = speedloanPreview(cust, appDesc);
		int status = dot.getCreditPhase();
		// 授信信息1.没有申请成功的显示产品直接拿额度 2.有申请成功的 就是显示额度 3.审批中 4.认证项都做过 未提交显示有笔钱
		boolean creditInfos = false;
		boolean fastProducts = false;
		boolean loanProducts = false;
		String[] reqests = refreshFields.split(",");
		for (String string : reqests) {
			if (TextConstant.creditInfo.equals(string)) {
				creditInfos = true;
			}
			if (TextConstant.fastProducts.equals(string)) {
				fastProducts = true;
			}
			if (TextConstant.loanProducts.equals(string)) {
				loanProducts = true;
			}
		}

		CreditInfoDto creditInfo = new CreditInfoDto();// 授信信息
		List<CustProductApply> productApplyList = new ArrayList<CustProductApply>();
		List<CustProductApply> productApplyLists = new ArrayList<CustProductApply>();

		String mobile = null;
		if (cust.getCustId() != null) {
			CustAccount custAccount = custAccountService.findByCustId(cust.getCustId());
			if (null != custAccount) {
				mobile = custAccount.getUserName();
			}
		}
		List<ProcessSpecial> processSpecials = processSpecialService.findAllByVersion(appDesc, mobile);
		if (null == cust.getCustId()) {
			creditInfo = new CreditInfoDto();
			creditInfo.setPromptMsg("点击拿钱");
			results.setCreditInfo(creditInfo);
		} else {
			if (creditInfos) {
				productApplyList = custProductApplyService.findByCustNot(cust.getCustId());
				productApplyLists = custProductApplyService.findByCustId(cust.getCustId());
				results.setCreditInfo(creditInfoDtoReturn(creditInfo, cust, appDesc, status, productApplyLists,processSpecials));
			}
			results.setCreditInfo(creditInfo);
		}
		// 快贷产品列表 按钮配置 // 贷款列表
		if (fastProducts || loanProducts) {

			fastProductsReturn(results, accessToken, cust, appDesc, pageIndex, pageSize, fastProducts, loanProducts, status, productApplyList, mobile, processSpecials);
		}
		return results;
	}

	/**
	 * 快贷首页2.0
	 * 
	 * @author zhaoqi01
	 * @param cust
	 * @return
	 * @throws Exception
	 */
	@Log
	public SpeedloanIndexDto index(Cust cust, String accessToken, String appDesc, Long productId, int pageIndex, int pageSize) throws Exception {
		SpeedloanIndexDto result = new SpeedloanIndexDto();
		int start = 0;
		int end = 0;
		if (pageIndex != 0) {
			start = pageIndex * pageSize;
		}
		end = start + pageSize;

		String mobile = null;
		if (cust.getCustId() != null) {
			CustAccount custAccount = custAccountService.findByCustId(cust.getCustId());
			if (null != custAccount) {
				mobile = custAccount.getUserName();
			}
		}
		List<ProcessSpecial> processSpecials = processSpecialService.findAllByVersion(appDesc, mobile);

		if (Utility.isNullOrEmpty(processSpecials)) {
			// 默认展示信用花 (20171201 信用花下线 改为默认显示 闪贷)
			ProcessSpecial processSpecial = processSpecialService.findByProductId(3L);
			if (null != processSpecial) {
				processSpecials = new ArrayList<ProcessSpecial>();
				processSpecials.add(processSpecial);
			}
		} else {
			// 判断 却小钱 缺块钱 是否存在 存在删除 缺大钱
			if (cust.getCustId() != null) {
				boolean flag = false;
				for (ProcessSpecial processSpecial : processSpecials) {
					// 如果存在 缺小钱 缺块钱
					if (processSpecial.getProductId().equals(6L) || processSpecial.getProductId().equals(25L)) {
						// 记录标志 存在则记录 不确定产品存储顺序
						flag = true;
					}
				}
				if (flag) {
					Iterator<ProcessSpecial> iter = processSpecials.iterator();
					while (iter.hasNext()) {
						ProcessSpecial processSpecial = iter.next();
						if (processSpecial.getProductId().equals(31L) && flag) {
							iter.remove();
						}
					}
				}
			}
		}

		List<MerchantProduct> hotProducts = this.getHotProducts(appDesc, cust.getCustId());

		List<Map<String, Long>> paginationList = this.getPaginationList(cust, productId, processSpecials, hotProducts);

		List<Map<String, Long>> currentPageDataList = null;

		if (start >= paginationList.size()) {
			return result;
		}

		if (end <= paginationList.size()) {
			currentPageDataList = paginationList.subList(start, end);
		} else {
			currentPageDataList = paginationList.subList(start, paginationList.size());
		}

		Map<Long, MerchantProduct> allMerchantProduct = merchantProductService.findAll();
		for (Map<String, Long> map : currentPageDataList) {
			Long pId = map.get("productId");
			if (map.get("type") == 1) { // 快贷产品
				result.getPrecheckItemList().add(this.getPrecheckItemV2(cust, allMerchantProduct.get(pId.longValue())));
			} else { // 热门贷款
				result.getHotProductList().add(this.getHotProductDto(cust, accessToken, allMerchantProduct.get(pId.longValue())));
			}
		}

		return result;
	}

	/**
	 * 封装快贷产品数据项
	 * 
	 * @author zhaoqi01
	 * @param cust
	 * @param merchantProduct
	 * @return
	 * @throws Exception
	 */
	private SpeedloanPrecheckItemV2Dto getPrecheckItemV2(Cust cust, MerchantProduct merchantProduct) throws Exception {
		SpeedloanPrecheckItemV2Dto result = new SpeedloanPrecheckItemV2Dto();
		Map<String, Object> precheckResult = this.precheck(merchantProduct.getProductId(), cust, false);
		SpeedloanPrecheckItemDto precheckItemDto = (SpeedloanPrecheckItemDto) precheckResult.get("precheckItemDto");

		// 拼接额度、费率
		StringBuilder sb = new StringBuilder();
		sb.append(TextConstant.E_DU).append(precheckItemDto.getLimitRange()).append(TextConstant.KONG_GE).append(TextConstant.SHU_GANG).append(TextConstant.KONG_GE).append(TextConstant.FEI_LV)
				.append(precheckItemDto.getMonthlyRate());

		String productDesc = sb.toString();
		sb.delete(0, sb.length());

		// 拼接XXX人成功申请
		sb.append(merchantProduct.getProductApplycount()).append(TextConstant.CHENG_GONG_SHEN_QING);

		result.setProductId(precheckItemDto.getProductId());
		result.setProductName(precheckItemDto.getProductName());
		result.setProductIcon(precheckItemDto.getProductIcon());
		result.setDisplayWay("1");
		result.setJumpUrl(precheckItemDto.getJumpUrl());
		result.setProductDesc(productDesc);
		result.setApplyQty(sb.toString());
		result.setCreditPhase(precheckItemDto.getCreditPhase());
		result.setCreditDesc(this.getSpeedloanItemTitle(precheckItemDto));
		result.setGetLimit(precheckItemDto.getGetLimit());
		result.setExpiryTime(precheckItemDto.getExpiryTime());
		result.setAuthItems(precheckItemDto.getAuthItems());

		return result;
	}

	/**
	 * 快贷产品项title文案
	 * 
	 * @author zhaoqi01
	 * @param precheckItemDto
	 * @return
	 * @throws ParseException
	 */
	private String getSpeedloanItemTitle(SpeedloanPrecheckItemDto precheckItemDto) throws ParseException {
		String creditDesc = "";
		String title = speedloanItemTitles.get(precheckItemDto.getCreditPhase());
		if (null == title) {
			creditDesc = precheckItemDto.getCreditDesc();
		} else {
			if (title.indexOf("{") != -1) {
				String dateStr = "";
				String frozenTime = precheckItemDto.getFrozenTime();
				if (StringUtils.isBlank(frozenTime)) {
					creditDesc = TextConstant.E_DU_SHI_BAI;
				} else {
					dateStr = ConcurrentDateUtil.formatMonthDayStr(ConcurrentDateUtil.strToDate(frozenTime));
					creditDesc = title.replace(DATE_REGEX, dateStr);
				}
			} else {
				creditDesc = title;
			}
		}
		return creditDesc;
	}

	/**
	 * 封装热门贷款数据项
	 * 
	 * @author zhaoqi01
	 * @param cust
	 * @param accessToken
	 * @return
	 * @throws Exception
	 */
	private SpeedloanHotProductDto getHotProductDto(Cust cust, String accessToken, MerchantProduct merchantProduct) throws Exception {
		SpeedloanHotProductDto result = new SpeedloanHotProductDto();

		StringBuilder sb = new StringBuilder();

		// 拼接额度文案
		sb.append(TextConstant.E_DU).append(TextConstant.KONG_GE).append(TextConstant.MAO_HAO).append(TextConstant.KONG_GE).append(merchantProduct.getProductMincredit() / 100).append(TextConstant.ZHONG_HUA_XIAN)
				.append(merchantProduct.getProductMaxcredit() / 100).append(TextConstant.YUNA);

		String amtStr = sb.toString();
		sb.delete(0, sb.length());

		// 拼接费率文案
		sb.append(TextConstant.FEI_LV).append(TextConstant.KONG_GE).append(TextConstant.MAO_HAO).append(TextConstant.KONG_GE).append(merchantProduct.getProductRate());

		String rateStr = sb.toString();
		sb.delete(0, sb.length());

		String applyCountStr = merchantProduct.getProductApplycount() + TextConstant.CHENG_GONG_SHEN_QING;

		String productDesc = merchantProduct.getTag();
		if (productDesc.split(",").length > 2) {
			String[] descArr = productDesc.split(",");
			sb.append(descArr[0].trim()).append(TextConstant.DOU_HAO).append(descArr[1].trim());
			productDesc = sb.toString();
		}

		// 拼接返现文案
		String productRemark = TextConstant.FAN_XIAN_TEXT;
		if (cust.getCustId() != null) {
			CustAbility maxAbility = custAbilityService.findMaxAbilityByCustId(cust.getCustId());
			if (null != maxAbility) {
				AbilityEnum abilityEnum = EnumExtUtil.getEnumOnValue(AbilityEnum.class, String.valueOf(maxAbility.getAbilityId()), "code");
				productRemark = PRODUCT_REMARK.replace(AMT_REGEX, abilityEnum.getAmt() / 100 + "");
			}
		}

		result.setProductId(merchantProduct.getProductId());
		result.setProductName(merchantProduct.getProductName());
		result.setProductIcon(merchantProduct.getProductIcon());
		result.setProductAmt(amtStr);
		result.setProductApplyCount(applyCountStr);
		result.setProductRate(rateStr);
		result.setProductLabel(productDesc);
		result.setProductRemark(productRemark);
		result.setDisplayWay("1");
		result.setFeatureTag(merchantProduct.getFeatureTag());
		if (merchantProduct.getStar().intValue() == 0) {
			result.setJumpUrl(merchantProduct.getProductUri());
		} else {
			String jumpUrl = productDetailUrl + merchantProduct.getProductId() + "/" + accessToken;
			result.setJumpUrl(jumpUrl);
		}

		return result;
	}

	/**
	 * 3.0接口修改
	 *
	 * @author zhaoqi01
	 * @param productId
	 * @param processSpecials
	 * @return
	 */
	private List<Map<String, Long>> getPaginationLists(Cust cust, Long productId, List<ProcessSpecial> processSpecials, List<MerchantProduct> hotProducts) {
		List<Map<String, Long>> list = new ArrayList<Map<String, Long>>();
		List<Long> speedloanProductIds = new ArrayList<Long>();
		if (productId != null) {
			for (ProcessSpecial processSpecial : processSpecials) {
				if (processSpecial.getProductId().longValue() == productId) {
					speedloanProductIds.add(processSpecial.getProductId());

					Map<String, Long> map = new HashMap<String, Long>();
					map.put("type", 1L);
					map.put("productId", processSpecial.getProductId());
					list.add(map);
					break;
				}
			}
		} else {
			for (ProcessSpecial processSpecial : processSpecials) {
				speedloanProductIds.add(processSpecial.getProductId());

				Map<String, Long> map = new HashMap<String, Long>();
				map.put("type", 1L);
				map.put("productId", processSpecial.getProductId());
				list.add(map);
			}
		}

		// 如果用户未登录只显示快贷产品，不显示热门贷款
		if (cust.getCustId() == null) {
			return list;
		}
		// 如果用户有申请快贷产品的审批结果：成功或失败，就显示热门产品，否则不显示
		if (speedloanProductIds.size() > 0) {
			List<UserTempExt> userTemp = userTempService.findMyAplly(cust.getCustId());
			if (0 == userTemp.size()) {
				long count = custProductApplyService.findHasResultByCustAndProduct(cust.getCustId(), speedloanProductIds);
				if (count > 0) {
					return list;
				}
			}
		}

		for (MerchantProduct merchantProduct : hotProducts) {
			Map<String, Long> map = new HashMap<String, Long>();
			map.put("type", 2L);
			map.put("productId", merchantProduct.getProductId());
			list.add(map);
		}
		return list;
	}

	/**
	 * 分页元数据
	 * 
	 * @author zhaoqi01
	 * @param productId
	 * @param processSpecials
	 * @return
	 */
	private List<Map<String, Long>> getPaginationList(Cust cust, Long productId, List<ProcessSpecial> processSpecials, List<MerchantProduct> hotProducts) {
		List<Map<String, Long>> list = new ArrayList<Map<String, Long>>();
		List<Long> speedloanProductIds = new ArrayList<Long>();
		if (productId != null) {
			for (ProcessSpecial processSpecial : processSpecials) {
				if (processSpecial.getProductId().longValue() == productId) {
					speedloanProductIds.add(processSpecial.getProductId());

					Map<String, Long> map = new HashMap<String, Long>();
					map.put("type", 1L);
					map.put("productId", processSpecial.getProductId());
					list.add(map);
					break;
				}
			}
		} else {
			for (ProcessSpecial processSpecial : processSpecials) {
				speedloanProductIds.add(processSpecial.getProductId());

				Map<String, Long> map = new HashMap<String, Long>();
				map.put("type", 1L);
				map.put("productId", processSpecial.getProductId());
				list.add(map);
			}
		}

		// 如果用户未登录只显示快贷产品，不显示热门贷款
		if (cust.getCustId() == null) {
			return list;
		}

		// 如果用户有申请快贷产品的审批结果：成功或失败，就显示热门产品，否则不显示
		if (speedloanProductIds.size() > 0) {
			for (Long long1 : speedloanProductIds) {
				Map<String, Long> map = new HashMap<String, Long>();
				map.put("type", 2L);
				map.put("productId", long1);
				list.add(map);
			}
			return list;
		}

		for (MerchantProduct merchantProduct : hotProducts) {
			Map<String, Long> map = new HashMap<String, Long>();
			map.put("type", 2L);
			map.put("productId", merchantProduct.getProductId());
			list.add(map);
		}
		return list;
	}

	private List<MerchantProduct> getHotProducts(String appDesc, Long custId) {
		List<MerchantProduct> list = new ArrayList<MerchantProduct>();
		Map<Long, MerchantProduct> all = merchantProductService.findAll();
		for (Entry<Long, MerchantProduct> entry : all.entrySet()) {
			MerchantProduct product = entry.getValue();
			if (product.getIsHot() && !product.getIsTechnical()) {
				list.add(product);
			}
		}
		this.excludeFromPlantform(list, appDesc);
		this.excludeFromChannel(list, custId);
		return list;
	}

	/**
	 * 产品控制条件过滤
	 * 
	 * @author zhaoqi01
	 * @param merchantProducts
	 * @param appDesc
	 */
	private void excludeFromPlantform(List<MerchantProduct> merchantProducts, String appDesc) {
		if (StringUtils.isEmpty(appDesc)) {
			appDesc = "creditcat;1.3.1;ios";
		}
		Iterator<MerchantProduct> iterator = merchantProducts.iterator();
		while (iterator.hasNext()) {
			boolean unfit = false;
			MerchantProduct merchantProduct = iterator.next();
			List<ProductCondition> conditions = productConditionService.findByProductIdAndType(merchantProduct.getProductId(), "3");
			if (Utility.isNullOrEmpty(conditions)) {
				unfit = true;
			} else {
				for (ProductCondition condition : conditions) {
					String conditionValue = condition.getConditionValue();
					if ((!StringUtils.isEmpty(conditionValue)) && appDesc.trim().toLowerCase().equals(conditionValue.toLowerCase().trim())) {
						unfit = false;
						break;
					} else {
						unfit = true;
					}
				}
			}

			if (unfit) {
				iterator.remove();
			}
		}
	}

	/**
	 * 过滤渠道用户
	 * 
	 * @author zhaoqi01
	 * @param merchantProducts
	 * @param custId
	 */
	private void excludeFromChannel(List<MerchantProduct> merchantProducts, Long custId) {

		if (ObjectUtils.equals(null, custId)) {
			return;
		}

		List<UserTempExt> myApllyedChannel = userTempService.findMyApllyedChannel(custId);
		if (Utility.isNullOrEmpty(myApllyedChannel)) {
			return;
		}

		Iterator<MerchantProduct> iterator = merchantProducts.iterator();
		while (iterator.hasNext()) {
			MerchantProduct merchantProduct = iterator.next();
			for (UserTempExt ext : myApllyedChannel) {
				RegisterChannel registerChannel = ext.getRegisterChannel();
				if (StringUtils.equals(registerChannel.getChannelDesc(), merchantProduct.getProductName())) {
					iterator.remove();
				}
			}
		}
	}

	/**
	 * 快贷预检或者申请
	 * 
	 * @author zhaoqi01
	 * @param paramMap
	 * @param cust
	 * @return
	 * @throws Exception
	 */
	@Log
	@Transactional(propagation = Propagation.REQUIRED)
	public SpeedloanPrecheckItemDto creditPrecheck(Map<String, Object> paramMap, Cust cust) throws Exception {
		Long productId = Long.parseLong(paramMap.get("productId") + "");
		boolean creditSev = "0".equals(paramMap.get("creditSev") + "");
		paramMap.remove("creditSev");
		paramMap.remove("productId");
		// 预检
		Map<String, Object> resultMap = this.precheck(productId, cust, creditSev);

		SpeedloanPrecheckItemDto precheckItemDto = (SpeedloanPrecheckItemDto) resultMap.get("precheckItemDto");

		// 预检返回
		if (creditSev)
			return precheckItemDto;

		int status = (int) resultMap.get("status");
		Long specialId = (Long) resultMap.get("specialId");
		Object processSpecialCustOld = resultMap.get("processSpecialCust");
		ProcessSpecialCust processSpecialCust = processSpecialCustOld == null ? null : (ProcessSpecialCust) processSpecialCustOld;

		// 如果没有可申请的产品，返回
		if (precheckItemDto.getCreditPhase() != 5) {
			return precheckItemDto;
		}

		if (status == 2) { // 如果有在申请中的认证项，提交快贷流程 ； 并且新增或更新产品申请记录，状态为22（快贷流程申请中）
			if (processSpecialCust == null) {
				processSpecialCust = new ProcessSpecialCust(specialId, cust.getCustId(), 1, JacksonUtil.Obj2Json(paramMap));
				processSpecialCustService.insert(processSpecialCust);
			} else {
				processSpecialCust.setStatus(1);
				processSpecialCust.setCustParam(JacksonUtil.Obj2Json(paramMap));
				processSpecialCustService.update(processSpecialCust);
			}

			// 设置授信状态22代表快贷流程提交中
			CustProductApply applyProduct = resultMap.get("applyProduct") == null ? null : (CustProductApply) resultMap.get("applyProduct");
			if (applyProduct == null) { // 新增
				applyProduct = new CustProductApply();
				applyProduct.setCustId(cust.getCustId());
				applyProduct.setProductId(productId);
				applyProduct.setAuditResult(22);
				custProductApplyService.insert(applyProduct);
			} else { // 更新
				applyProduct.setAuditResult(22);
				applyProduct.setIsApply(true);
				custProductApplyService.update(applyProduct);
			}

			precheckItemDto.setCreditPhase(2);
			return precheckItemDto;
		}

		// 认证项全部通过，申请产品
		List<ItemStatusDto> itemStatusDtos = (List<ItemStatusDto>) resultMap.get("itemStatusDtos");
		List<CustSupplementItem> custSupplementItems = (List<CustSupplementItem>) resultMap.get("custSupplementItems");
		ProductApplyResultDto productApplyResultDto = creditProductService.apply(cust, productId, paramMap, custSupplementItems, itemStatusDtos);

		if (productApplyResultDto.getCheckState() == 1) { // 不存在失效认证项
			// 查询产品申请记录
			CustProductApply newApplyProduct = custProductApplyService.findNewApplyProduct(productId, cust.getCustId());
			Integer auditResult = newApplyProduct.getAuditResult();
			if (auditResult == 0) {// 如果授信失败，设置下次申请的时间
				precheckItemDto.setCreditPhase(4);
				precheckItemDto.setFrozenTime(newApplyProduct.getCreditApplyTime());
				return precheckItemDto;
			} else if (auditResult == 1) {
				auditResult = 3;
			}
			precheckItemDto.setCreditPhase(auditResult);
			return precheckItemDto;

		} else { // 存在失效认证项
			// 在申请产品时如果有失效的认证项，会将认证项重置，所以需要重新查询认证项状态
			List<SpeedloanAuthItemDto> authItems = precheckItemDto.getAuthItems();
			for (SpeedloanAuthItemDto speedloanAuthItemDto : authItems) {
				if (speedloanAuthItemDto.getCategory() == 0) {
					ItemStatusDto itemStatusDto = creditRepositoryService.getStatus(speedloanAuthItemDto.getItemCode() + "", 0, cust);
					BeanUtil.copy(itemStatusDto, speedloanAuthItemDto);
				}
			}
			precheckItemDto.setCreditPhase(0);
			return precheckItemDto;
		}
	}

	/**
	 * 快贷预检列表
	 * 
	 * @author zhaoqi01
	 * @param cust
	 * @return
	 * @throws Exception
	 */
	@Log
	@Transactional(propagation = Propagation.REQUIRED)
	public SpeedloanPrecheckDto precheckList(Cust cust, String appDesc) throws Exception {
		SpeedloanPrecheckDto result = new SpeedloanPrecheckDto();
		CustAccount param = new CustAccount();
		param.setCustId(cust.getCustId());
		List<CustAccount> custAccounts = custAccountService.find(param);
		List<ProcessSpecial> processSpecials = new ArrayList<ProcessSpecial>();
		// 解析productId
		String productId = "";
		if (StringUtils.isNotBlank(appDesc)) {
			Map<String, Object> map = JacksonUtil.Json2Map(appDesc);
			if (null != map.get("productId") && map.get("productId").toString().trim().length() > 0) {
				productId = (String) map.get("productId");
				ProcessSpecial processSpecial = processSpecialService.findByProductId(Long.parseLong(productId));
				if (null != processSpecial) {
					processSpecials.add(processSpecial);
				}
			} else {
				String appDescStr = map.get("appDesc") == null ? null : (String) map.get("appDesc");
				if (custAccounts != null && custAccounts.size() > 0) {
					processSpecials = processSpecialService.findAllByVersion(appDescStr, custAccounts.get(0).getUserName());
					// 如果预检产品都不通过默认展示信用花
					if (Utility.isNullOrEmpty(processSpecials)) {
						ProcessSpecial processSpecial = processSpecialService.findByProductId(3L);
						if (null != processSpecial) {
							processSpecials = new ArrayList<ProcessSpecial>();
							processSpecials.add(processSpecial);
						}
					} else {
						// 判断 却小钱 缺块钱 是否存在 存在删除 缺大钱
						boolean flag = false;
						for (ProcessSpecial processSpecial : processSpecials) {
							// 如果存在 缺小钱 缺块钱
							if (processSpecial.getProductId().equals(6L) || processSpecial.getProductId().equals(25L)) {
								// 记录标志 存在则记录 不确定产品存储顺序
								flag = true;
							}
						}
						// 如果缺小钱 缺快钱存在则移除缺大钱
						if (flag) {
							Iterator<ProcessSpecial> iter = processSpecials.iterator();
							while (iter.hasNext()) {
								ProcessSpecial processSpecial = iter.next();
								if (processSpecial.getProductId().equals(31L) && flag) {
									iter.remove();
								}
							}
						}
					}
				} else {
					processSpecials = processSpecialService.findAllByVersion(appDescStr, null);
				}
			}
		}

		// 获取产品数据
		List<MerchantProduct> products = new ArrayList<MerchantProduct>();
		if (productId.trim().length() > 0) {// productId不为空时，只取一个product
			MerchantProduct merchantProduct = new MerchantProduct();
			merchantProduct = merchantProductService.findById(Long.valueOf(productId));
			products.add(merchantProduct);
		} else {// 为空默认取所有
			products = merchantProductService.findTechnialProduct(true);
		}

		List<Long> productIdList = this.getProductIdList(products);
		for (ProcessSpecial processSpecial : processSpecials) {
			if (productIdList.contains(processSpecial.getProductId())) {
				Map<String, Object> resultMap = this.precheck(processSpecial.getProductId(), cust, false);
				result.getPrecheckItemList().add((SpeedloanPrecheckItemDto) resultMap.get("precheckItemDto"));
			}
		}

		return result;
	}

	/**
	 * 根据产品id预检快贷结果
	 * 
	 * @author zhaoqi01
	 * @param productId
	 * @param cust
	 * @return
	 * @throws Exception
	 */
	@Log
	public Map<String, Object> precheck(Long productId, Cust cust, boolean checkCust) throws Exception {
		Map<String, Object> result = new HashMap<String, Object>();
		// 查询产品详情
		MerchantProduct merchantProduct = merchantProductService.findById(productId);
		// 查询用户对该产品的申请情况
		CustProductApply newApplyProduct = custProductApplyService.findNewApplyProduct(productId, cust.getCustId());
		// 根据productId查询所属流程
		ProcessSpecial processSpecial = this.getProcessSpecial(productId);

		// 获取认证项状态
		List<ItemStatusDto> itemStatusDtos = authItemExtService.getItemStatusDtoByCustAndProduct(cust, productId);

		// 获取补充认证项状态
		List<CustSupplementItemExt> custSupplementItemExtList = custSupplementItemService.findAllItemExtsByCustAndProduct(cust, productId);
		List<CustSupplementItem> custSupplementItems = new ArrayList<CustSupplementItem>();
		for (CustSupplementItemExt custSupplementItemExt : custSupplementItemExtList) {
			custSupplementItems.add(custSupplementItemExt.getCustSupplementItem());
		}

		// 检查信用项的状态
		int status = authItemExtService.checkAllItemsStatus(itemStatusDtos, custSupplementItems);

		// 查询快速贷款流程记录
		ProcessSpecialCust processSpecialCustOld = null;
		if (cust.getCustId() != null) {
			processSpecialCustOld = processSpecialCustService.findForUpdate(new ProcessSpecialCust(processSpecial.getSpecialId(), cust.getCustId(), null, null));
		}

		// 有未申请、或者有失败的认证项，需要修改用户快贷流程的状态; 并且需要修改状态为22（认证项认证中）的产品申请记录的状态为0（失败）
		if (status == 0 || status == 3 || status == 4) {
			this.handleProcessSpecialCust(status, processSpecialCustOld);

			if (newApplyProduct != null && newApplyProduct.getAuditResult() == 22) {
				newApplyProduct.setAuditResult(0);
				newApplyProduct.setIsApply(true);
				newApplyProduct.setCreditApplyTime(ConcurrentDateUtil.formatDateTime(new Date()));
				newApplyProduct.setRejectMsg(CustProductApplyService.AUTH_ITEM_UNDONE_MSG);
				custProductApplyService.update(newApplyProduct);
			}
		}

		// 获取授信状态
		int creditPhase = this.getCreditPhase(status, newApplyProduct, processSpecialCustOld);
		String creditDesc = "";
		if (creditPhase == 3 && processSpecial.getJoinLoanApi()) {
			// 如果是授信成功并且是已经统一对接的产品，返回8（放贷中）
			creditPhase = 8;
			creditDesc = "授信成功，可申请放款";
		} else if (creditPhase > 7) {
			for (ProductAuditResultEnum e : ProductAuditResultEnum.values()) {
				if (creditPhase == e.getCode()) {
					creditDesc = e.getDesc();
				}
			}
			creditPhase = 8; // 授信后状态统一返回8到前端
		}

		// 校验用户资格
		if (checkCust && creditPhaseForCheckUser.contains(creditPhase)) {
			// 查询对应产品是否有校验规则
			List<ProductCheckcustItem> checkcustItems = productCheckcustItemService.findByProductId(productId);
			if (null != checkcustItems && checkcustItems.size() > 0) {
				CheckCustResultDto checkResult = this.getProductCheckCustServiceImpl(productId).checkCust(cust, productId, checkcustItems, itemStatusDtos, custSupplementItems, newApplyProduct);
				if (checkResult.getCheckResult() == 2) {
					SpeedloanPrecheckItemDto precheckItemDto = new SpeedloanPrecheckItemDto.Builder().productId(merchantProduct.getProductId()).productName(processSpecial.getSpecialName()).tag(merchantProduct.getTag())
							.productIcon(merchantProduct.getProductIcon()).jumpUrl(merchantProduct.getProductUri()).maxAmt(merchantProduct.getProductMaxcredit()).minAmt(merchantProduct.getProductMincredit())
							.monthlyRate(merchantProduct.getProductRate()).limitRange(Utility.unitMaxMin(merchantProduct.getProductMincredit(), merchantProduct.getProductMaxcredit())).preCheckResult(checkResult).build();
					result.put("precheckItemDto", precheckItemDto);
					return result;
				}
			}
		}

		// 根据机构版征信的失败状态做单独处理
		creditPhase = this.handlerForeignCredit(cust, productId, creditPhase, itemStatusDtos, newApplyProduct);

		// 封装authItems
		List<SpeedloanAuthItemDto> authItems = this.packageAuthItems(itemStatusDtos, custSupplementItemExtList, productId);

		// 获取额度过期时间
		Long creditExpiryTime = 0L;
		if (null != newApplyProduct && StringUtils.isNotBlank(newApplyProduct.getCreditExpiretime())) {
			creditExpiryTime = ConcurrentDateUtil.strToDate(newApplyProduct.getCreditExpiretime()).getTime();
		}

		SpeedloanPrecheckItemDto precheckItemDto = new SpeedloanPrecheckItemDto.Builder().productId(merchantProduct.getProductId()).productName(processSpecial.getSpecialName())
				.productIcon(merchantProduct.getProductIcon()).jumpUrl(merchantProduct.getProductUri()).maxAmt(merchantProduct.getProductMaxcredit()).minAmt(merchantProduct.getProductMincredit())
				.monthlyRate(merchantProduct.getProductRate()).limitRange(Utility.unitMaxMin(merchantProduct.getProductMincredit(), merchantProduct.getProductMaxcredit())).creditPhase(creditPhase).creditDesc(creditDesc)
				.frozenTime(newApplyProduct == null ? null : newApplyProduct.getCreditApplyTime()).authItems(authItems).preCheckResult(CheckCustResultDto.success())
				.getLimit(newApplyProduct == null ? 0 : newApplyProduct.getCreditAmt()).expiryTime(creditExpiryTime).salesModel(merchantProduct.getSalesModel()).featureTag(merchantProduct.getFeatureTag()).build();

		result.put("precheckItemDto", precheckItemDto);
		result.put("status", status);
		result.put("processSpecialCust", processSpecialCustOld);
		result.put("applyProduct", newApplyProduct);
		result.put("specialId", processSpecial.getSpecialId());
		result.put("itemStatusDtos", itemStatusDtos);
		result.put("custSupplementItems", custSupplementItems);
		return result;
	}

	/**
	 * 根据机构版征信的失败状态做单独处理
	 * 
	 * @author zhaoqi01
	 * @param itemStatusDtos
	 * @param newApplyProduct
	 * @return
	 * @throws ParseException
	 */
	private int handlerForeignCredit(Cust cust, Long productId, int creditPhase, List<ItemStatusDto> itemStatusDtos, CustProductApply newApplyProduct) throws ParseException {
		if (cust == null || cust.getCustId() == null) {
			return creditPhase;
		}
		if (null != newApplyProduct) {
			// 如果该产品已经提交了资料正在审批或者已经审批成功了，则无需根据机构版征信的预审失败的结果做处理
			Integer auditResult = newApplyProduct.getAuditResult();
			if (auditResult == 2 || auditResult == 1 || (auditResult >= 7 && auditResult != 22)) {
				return creditPhase;
			}
		}

		for (ItemStatusDto itemStatusDto : itemStatusDtos) {
			if (itemStatusDto.getItemCode().intValue() == AuthItemEnum.FOREIGN_CREDIT.getCode()) {
				if ("3".equals(itemStatusDto.getStatus())) {
					// 如果是失败状态，查询机构版征信的具体状态是否为预审拒绝状态，如果是则设置产品授信失败，并指定下次申请的时间
					CreditAssure creditAssure = creditAssureService.findByProcessId(cust.getLastProccessId());
					if (creditAssure.getAssureStatus().intValue() == AssureStatusEnum.PreAuditFail.getCode() && !creditAssure.computeExpire()) {
						if (null == newApplyProduct) {
							newApplyProduct = new CustProductApply();
							newApplyProduct.setProductId(productId);
							newApplyProduct.setCustId(cust.getCustId());
							newApplyProduct.setAuditResult(0);
							newApplyProduct.setRejectMsg("机构版征信预审拒绝");
							newApplyProduct.setIsApply(true);
							newApplyProduct.setCreditApplyTime(creditAssure.getExpiredTime());
							custProductApplyService.insert(newApplyProduct);
						} else {
							newApplyProduct.setAuditResult(0);
							newApplyProduct.setRejectMsg("机构版征信预审拒绝");
							newApplyProduct.setIsApply(true);
							newApplyProduct.setCreditApplyTime(creditAssure.getExpiredTime());
							custProductApplyService.update(newApplyProduct);
						}
						return 4;
					}
				}
				break;
			}
		}
		return creditPhase;
	}

	public List<SpeedloanAuthItemDto> packageAuthItems(List<ItemStatusDto> authItems, List<CustSupplementItemExt> custSupplementItemExtList, Long productId) {
		List<ProcessSpecialItem> specialItems = processSpecialItemService.findByProductId(productId);

		if (Utility.isNullOrEmpty(authItems)) {
			return this.sortSpeedloanAuthItemsForSupplementItems(custSupplementItemExtList, specialItems);
		} else if (Utility.isNullOrEmpty(custSupplementItemExtList)) {
			return this.sortSpeedloanAuthItemsForAuthItems(authItems, specialItems);
		}

		List<SpeedloanAuthItemDto> result = new ArrayList<SpeedloanAuthItemDto>();
		for (ProcessSpecialItem specialItem : specialItems) {
			result.add(this.getAuthItemBySort(specialItem, authItems, custSupplementItemExtList));
		}
		return result;
	}

	private List<SpeedloanAuthItemDto> sortSpeedloanAuthItemsForAuthItems(List<ItemStatusDto> authItems, List<ProcessSpecialItem> specialItems) {
		List<SpeedloanAuthItemDto> result = new ArrayList<SpeedloanAuthItemDto>();

		for (ProcessSpecialItem specialItem : specialItems) {
			for (ItemStatusDto authItem : authItems) {
				if (specialItem.getItemType() == 0 && specialItem.getItemId().longValue() == authItem.getItemId()) {
					SpeedloanAuthItemDto target = new SpeedloanAuthItemDto();
					BeanUtil.copy(authItem, target);
					result.add(target);
					break;
				}
			}
		}
		return result;
	}

	private List<SpeedloanAuthItemDto> sortSpeedloanAuthItemsForSupplementItems(List<CustSupplementItemExt> custSupplementItemExtList, List<ProcessSpecialItem> specialItems) {
		List<SpeedloanAuthItemDto> result = new ArrayList<SpeedloanAuthItemDto>();
		for (ProcessSpecialItem specialItem : specialItems) {
			for (CustSupplementItemExt custSupplementItemExt : custSupplementItemExtList) {
				if (specialItem.getItemId() == 1 && specialItem.getItemId().longValue() == custSupplementItemExt.getProductSupplementItem().getItemId()) {
					result.add(this.packageAuthItemForSupplementItem(custSupplementItemExt));
					break;
				}
			}
		}
		return result;
	}

	private SpeedloanAuthItemDto getAuthItemBySort(ProcessSpecialItem specialItem, List<ItemStatusDto> authItems, List<CustSupplementItemExt> custSupplementItemExtList) {
		if (specialItem.getItemType() == 0) {// 原认证项
			for (ItemStatusDto authItem : authItems) {
				if (authItem.getItemId() == specialItem.getItemId()) {
					SpeedloanAuthItemDto item = new SpeedloanAuthItemDto();
					BeanUtil.copy(authItem, item);
					return item;
				}
			}
		} else { // 补充认证项
			for (CustSupplementItemExt custSupplementItemExt : custSupplementItemExtList) {
				if (custSupplementItemExt.getProductSupplementItem().getItemId().longValue() == specialItem.getItemId()) {
					return this.packageAuthItemForSupplementItem(custSupplementItemExt);
				}
			}
		}
		return null;
	}

	private SpeedloanAuthItemDto packageAuthItemForSupplementItem(CustSupplementItemExt custSupplementItemExt) {
		SpeedloanAuthItemDto item = new SpeedloanAuthItemDto();
		ProductSupplementItem productSupplementItem = custSupplementItemExt.getProductSupplementItem();
		item.setItemCode(productSupplementItem.getItemCode());
		item.setItemName(productSupplementItem.getItemName());
		item.setItemDesc(productSupplementItem.getItemDesc());
		item.setItemIcon(productSupplementItem.getItemIcon());
		item.setStatus(custSupplementItemExt.getCustSupplementItem().getStatus() + "");
		item.setCategory(productSupplementItem.getSupplementCategoryId());
		return item;
	}

	/**
	 * 获取授信状态
	 * 
	 * @author zhaoqi01
	 * @param status
	 * @param newApplyProduct
	 * @param processSpecialCustOld
	 * @return
	 * @throws ParseException
	 */
	private int getCreditPhase(int status, CustProductApply newApplyProduct, ProcessSpecialCust processSpecialCustOld) throws ParseException {
		// 不能再次申请
		if (null != newApplyProduct && !custProductApplyService.canProductApplyAgin(newApplyProduct)) {
			Integer auditResult = newApplyProduct.getAuditResult();
			if (auditResult == 1) { // 授信成功，额度获取成功
				return 3;
			} else if (auditResult == 0) { // 授信失败，额度获取失败
				return 4;
			} else if (auditResult == 2 || auditResult == 5 || auditResult == 22) { // 额度获取中
				return 2;
			} else if (auditResult == 7) {// 授信失败可挽回
				return 7;
			} else if (auditResult > 7) { // 授信后状态，签约中、放款中、还款中、已结清
				return auditResult;
			}
		}

		if (status == 0) {
			return 0;
		} else if (status == 3) {
			return 1;
		} else if (status == 4) {
			return 6;
		}

		// 判断用户快贷流程状态，如果为1，返回额度审批中;否则返回可以申请的状态
		if (processSpecialCustOld != null && processSpecialCustOld.getStatus() == 1)
			return 2;
		else
			return 5;

	}

	/**
	 * 当有失败的或者有没有完成的认证项时，需要修改对应ProcessSpecialCust的状态
	 * 
	 * @author zhaoqi01
	 * @param processSpecialCust
	 */
	private void handleProcessSpecialCust(int status, ProcessSpecialCust processSpecialCust) {
		if (null == processSpecialCust) {
			return;
		}
		if ((status == 0 || status == 3) && processSpecialCust.getStatus() != null && processSpecialCust.getStatus() == 1) {
			processSpecialCust.setStatus(0);
			processSpecialCust.setUpdateTime(null);
			processSpecialCustService.update(processSpecialCust);
		}
	}

	/**
	 * 根据产品id查询对应的快贷流程
	 * 
	 * @author zhaoqi01
	 * @param productId
	 * @return
	 */
	private ProcessSpecial getProcessSpecial(Long productId) {
		List<ProcessSpecial> processSpecials = processSpecialService.findAll();
		for (ProcessSpecial process : processSpecials) {
			if (process.getProductId().longValue() == productId.longValue()) {
				return process;
			}
		}
		return null;
	}

	private List<Long> getProductIdList(List<MerchantProduct> products) {
		List<Long> result = new ArrayList<Long>();
		for (MerchantProduct merchantProduct : products) {
			result.add(merchantProduct.getProductId());
		}
		return result;
	}

	/**
	 * 获取可申请的快贷产品
	 *
	 * @param cust
	 * @param appDesc
	 * @return
	 * @throws Exception
	 */
	@Log
	public SpeedloanCanApplyProductsDto getCanApplyProducts(Cust cust, String appDesc) throws Exception {
		SpeedloanCanApplyProductsDto result = new SpeedloanCanApplyProductsDto();
		List<MerchantProduct> products = this.getCanApplyFastProducts(cust.getCustId(), appDesc);
		// 如果预检产品都不通过默认展示信用花或闪贷
		if (Utility.isNullOrEmpty(products)) {
			products = merchantProductService.findSpeedloanProductsByVersion("defaultSelect", null);
			if (Utility.isNullOrEmpty(products)) {
				ProcessSpecial processSpecial = processSpecialService.findByProductId(3L);
				MerchantProduct XYH = merchantProductService.findById(3L);
				XYH.setProductName(processSpecial.getSpecialName());
				products.add(XYH);
			}
		}
		// 获取用户已申请的产品排除已失效的
		List<CustProductApply> custProductApplyList = this.getCustApplyFastPrdocts(cust.getCustId());
		if (custProductApplyList != null && custProductApplyList.size() > 0) {
			Iterator<MerchantProduct> it = products.iterator();
			while (it.hasNext()) {
				MerchantProduct product = it.next();
				for (CustProductApply custProductApply : custProductApplyList) {
					if (custProductApply.getProductId().equals(product.getProductId())) {
						it.remove();
						break;
					}
				}
			}
		}
		List<FastProduct> fastProducts = new ArrayList<>();
		for (MerchantProduct product : products) {
			FastProduct fastProduct = new FastProduct();
			fastProduct.setProductId(product.getProductId());
			fastProduct.setProductName(product.getProductName());
			fastProduct.setProductIcon(product.getProductIcon());
			fastProducts.add(fastProduct);
		}
		result.setFastProducts(fastProducts);
		return result;
	}

	/**
	 * 直接从数据库中获取的用户可申请的快贷产品
	 * 
	 * @param custId
	 * @param appDesc
	 * @return
	 */
	private List<MerchantProduct> getCanApplyFastProducts(Long custId, String appDesc) {
		List<MerchantProduct> products = new ArrayList<>();
		CustAccount param = new CustAccount();
		param.setCustId(custId);
		List<CustAccount> custAccounts = custAccountService.find(param);
		if (custAccounts != null && custAccounts.size() > 0) {
			products = merchantProductService.findSpeedloanProductsByVersion(appDesc, custAccounts.get(0).getUserName());
		}
		return products;
	}

	/**
	 * 预检2.0
	 * 
	 * @param cust
	 * @param appDesc
	 * @return
	 * @throws Exception
	 */
	@Log
	public SpeedloanPreviewDto speedloanPreview(Cust cust, String appDesc) throws Exception {
		SpeedloanPreviewDto result = new SpeedloanPreviewDto();
		// 查询可申请的快贷产品
		List<MerchantProduct> products = this.getCanApplyFastProducts(cust.getCustId(), appDesc);
		Set<Long> canApplyProductIds = new HashSet<>();
		if (products != null && products.size() > 0) {
			for (MerchantProduct product : products) {
				canApplyProductIds.add(product.getProductId());
			}
		}
		// 获取用户已申请的产品排除已失效的
		List<CustProductApply> custProductApplyList = this.getCustApplyFastPrdocts(cust.getCustId());
		if (custProductApplyList != null && custProductApplyList.size() > 0) {
			Set<Long> applyProductIds = new HashSet<>();
			for (CustProductApply custProductApply : custProductApplyList) {
				applyProductIds.add(custProductApply.getProductId());
			}
			if (applyProductIds.size() > 0 && canApplyProductIds.size() > 0) {
				if (applyProductIds.containsAll(canApplyProductIds)) {
					result.setCreditPhase(6);
					return result;
				}
			}
		}
		// 根据productId查询所属流程
		ProcessSpecial processSpecial = this.getProcessSpecial(0L);
		List<ProcessSpecialItem> processSpecialItems = processSpecialItemService.findByProductId(processSpecial.getProductId());

		// 获取认证项状态
		List<ItemStatusDto> itemStatusDtos = authItemExtService.getItemStatusDtoByCustAndProduct(cust, 0L);

		// 获取补充认证项状态
		List<CustSupplementItemExt> custSupplementItemExtList = custSupplementItemService.findItemExtsByCustAndProduct(cust, 0L);

		Map<Integer, AbstractItem> custAuthInfo = authItemExtService.getCustAuthInfo(itemStatusDtos, cust);

		// 获取失效的原始认证项
		List<Integer> expireAuthItems = authItemExtService.getExpireAuthItems(custAuthInfo);
		// 获取失效的补充认证项
		// List<Long> expireSupplementItems =
		// authItemExtService.getExpireSupplementItems(custSupplementItemList);

		// 重置失效认证项
		if (expireAuthItems != null && expireAuthItems.size() > 0) {
			for (ProcessSpecialItem item : processSpecialItems) {
				if (expireAuthItems.contains(item.getItemId())) {
					custCreditRepositoryService.getStatus(item.getItemId().toString(), 1, cust);
				}
			}
		}
		// 获取最新的原始认证项状态
		List<ItemStatusDto> itemStatusDtosNew = authItemExtService.getItemStatusDtoByCustAndProduct(cust, 0L);
		List<SpeedloanAuthItemDto> speedloanAuthItemDtos = packAuthItems(processSpecialItems, itemStatusDtosNew, custSupplementItemExtList);
		result.setCreditPhase(5);
		for (SpeedloanAuthItemDto item : speedloanAuthItemDtos) {
			if ("0".equals(item.getStatus()) || "3".equals(item.getStatus())) {
				result.setCreditPhase(0);
			}
		}
		result.setAuthItems(speedloanAuthItemDtos);
		return result;
	}

	/**
	 * 组装认证项
	 * 
	 * @param processSpecialItems
	 * @param itemStatusDtos
	 * @param custSupplementItemExtList
	 * @return
	 */
	private List<SpeedloanAuthItemDto> packAuthItems(List<ProcessSpecialItem> processSpecialItems, List<ItemStatusDto> itemStatusDtos, List<CustSupplementItemExt> custSupplementItemExtList) {
		List<SpeedloanAuthItemDto> speedloanAuthItemDtos = new ArrayList<>();
		// 按顺序将认证项放入一个集合
		for (ProcessSpecialItem item : processSpecialItems) {
			SpeedloanAuthItemDto speedloanAuthItemDto = new SpeedloanAuthItemDto();
			speedloanAuthItemDtos.add(speedloanAuthItemDto);
			if (item.getItemType().equals(0)) {
				for (ItemStatusDto itemStatusDto : itemStatusDtos) {
					if (itemStatusDto.getItemId().equals(item.getItemId())) {
						speedloanAuthItemDto.setItemCode(itemStatusDto.getItemCode());
						speedloanAuthItemDto.setItemName(itemStatusDto.getItemName());
						speedloanAuthItemDto.setItemIcon(itemStatusDto.getItemIcon());
						speedloanAuthItemDto.setItemDesc(itemStatusDto.getItemDesc());
						speedloanAuthItemDto.setStatus(itemStatusDto.getStatus());
						speedloanAuthItemDto.setFailReason(itemStatusDto.getFailReason());
						speedloanAuthItemDto.setCategory(0);
						break;
					}
				}
			} else {
				for (CustSupplementItemExt custSupplementItemExt : custSupplementItemExtList) {
					if (custSupplementItemExt.getProductSupplementItem().getItemId().equals(item.getItemId())) {
						speedloanAuthItemDto.setItemCode(custSupplementItemExt.getProductSupplementItem().getItemCode());
						speedloanAuthItemDto.setItemName(custSupplementItemExt.getProductSupplementItem().getItemName());
						speedloanAuthItemDto.setItemIcon(custSupplementItemExt.getProductSupplementItem().getItemIcon());
						speedloanAuthItemDto.setItemDesc(custSupplementItemExt.getProductSupplementItem().getItemDesc());
						speedloanAuthItemDto.setStatus(custSupplementItemExt.getCustSupplementItem().getStatus().toString());
						speedloanAuthItemDto.setFailReason(custSupplementItemExt.getCustSupplementItem().getFailReason());
						speedloanAuthItemDto.setCategory(1);
						break;
					}
				}
			}
		}
		return speedloanAuthItemDtos;
	}

	/**
	 * 获取用户已申请的产品排除可再次申请的
	 *
	 * @param custId
	 * @return
	 * @throws Exception
	 */
	private List<CustProductApply> getCustApplyFastPrdocts(Long custId) throws Exception {
		List<CustProductApply> custProductApplyList = custProductApplyService.findByCustId(custId);
		if (custProductApplyList.size() <= 0) {
			return custProductApplyList;
		}
		Iterator<CustProductApply> productIt = custProductApplyList.iterator();
		while (productIt.hasNext()) {
			CustProductApply product = productIt.next();
			Boolean applyFlag = custProductApplyService.canProductApplyAgin(product);
			if (applyFlag) {
				productIt.remove();
			}
			// if (product.getAuditResult().equals(1L)) {
			// if (StringUtils.isNotBlank(product.getCreditExpiretime())) {
			// long now = Calendar.getInstance().getTimeInMillis();
			// long expire =
			// ConcurrentDateUtil.strToDate(product.getCreditExpiretime()).getTime();
			// if (expire < now) {
			// productIt.remove();
			// }
			// }
			// } else {
			// if (product.getIsApply() &&
			// StringUtils.isNotBlank(product.getCreditApplyTime())) {
			// long now = Calendar.getInstance().getTimeInMillis();
			// long expire =
			// ConcurrentDateUtil.strToDate(product.getCreditApplyTime()).getTime();
			// if (expire < now) {
			// productIt.remove();
			// }
			// }
			// }
		}
		return custProductApplyList;
	}

	/**
	 * 提交审批
	 * 
	 * @param cust
	 * @param appDesc
	 * @param paramMap
	 * @throws Exception
	 */
	@Log
	public void speedloanCommit(Cust cust, String appDesc, Map<String, Object> paramMap) throws Exception {
		// 查询可申请产品
		SpeedloanCanApplyProductsDto speedloanCanApplyProducts = getCanApplyProducts(cust, appDesc);
		List<FastProduct> products = speedloanCanApplyProducts.getFastProducts();
		if (products == null || products.size() <= 0) {
			return;
		}
		// 根据productId查询所属流程
		ProcessSpecial processSpecial = this.getProcessSpecial(0L);
		List<ProcessSpecialItem> processSpecialItems = processSpecialItemService.findByProductId(processSpecial.getProductId());
		// 获取认证项状态
		List<ItemStatusDto> itemStatusDtos = authItemExtService.getItemStatusDtoByCustAndProduct(cust, 0L);

		// 获取补充认证项状态
		List<CustSupplementItemExt> custSupplementItemExtList = custSupplementItemService.findAllItemExtsByCustAndProduct(cust, 0L);

		List<SpeedloanAuthItemDto> speedloanAuthItemDtos = packAuthItems(processSpecialItems, itemStatusDtos, custSupplementItemExtList);
		// 判断失败认证项
		for (SpeedloanAuthItemDto item : speedloanAuthItemDtos) {
			if ("3".equals(item.getStatus())) {
				throw new SpeedloanCommitException("有失败认证项");
			}
		}
		// 如果认证项中存在未完成的将申请加入流程
		for (SpeedloanAuthItemDto authItemDto : speedloanAuthItemDtos) {
			if ("2".equals(authItemDto.getStatus())) {
				for (FastProduct product : products) {
					// 根据productId查询所属流程
					ProcessSpecial processSpecialElement = this.getProcessSpecial(product.getProductId());
					ProcessSpecialCust processSpecialCust = new ProcessSpecialCust(processSpecialElement.getSpecialId(), cust.getCustId(), 1, JacksonUtil.Obj2Json(paramMap));
					ProcessSpecialCust param = new ProcessSpecialCust();
					param.setCustId(cust.getCustId());
					param.setSpecialId(processSpecialElement.getSpecialId());
					List<ProcessSpecialCust> processSpecialCusts = processSpecialCustService.find(param);
					if (Utility.isNullOrEmpty(processSpecialCusts)) {
						processSpecialCustService.insert(processSpecialCust);
					}
					CustProductApply applyProduct = new CustProductApply();
					applyProduct.setCustId(cust.getCustId());
					applyProduct.setProductId(product.getProductId());
					applyProduct.setAuditResult(22);
					custProductApplyService.insert(applyProduct);
				}
				return;
			}
		}
		// 组装补充认证项
		Map<Long, CustSupplementItem> custSupplementItemMap = new HashMap<Long, CustSupplementItem>();
		for (CustSupplementItemExt custSupplementItemExt : custSupplementItemExtList) {
			custSupplementItemMap.put(custSupplementItemExt.getCustSupplementItem().getSupplementItemId(), custSupplementItemExt.getCustSupplementItem());
		}
		// 获取原始认证项详情
		Map<Integer, AbstractItem> custAuthInfo = authItemExtService.getCustAuthInfo(itemStatusDtos, cust);

		for (FastProduct product : products) {
			try {
				// 封装其他参数
				creditProductService.packageOtherParams(paramMap, cust, product.getProductId());

				// 产品申请
				ProductApplyResultVo applyResult = creditProductService.getProductApplyServiceImpl(product.getProductId()).apply(custAuthInfo, custSupplementItemMap, paramMap);

				// 4、处理申请结果
				creditProductService.handlerProductApplyResult(applyResult, cust, product.getProductId());
			} catch (Exception e) {
				continue;
			}

		}
	}

	/**
	 * 热门推荐列表
	 * 
	 * @param cust
	 * @param appDesc
	 * @param accessToken
	 * @return
	 * @throws Exception
	 */
	@Log
	public List<LoanProductsDto> popularRecommend(Cust cust, String appDesc, String accessToken, Map<String, Object> paramMap) throws Exception {
		Integer start;
		Integer limit;
		if (paramMap.get("showPosition") != null && paramMap.get("showPosition").equals(2)) {
			start = 0;
			limit = 4;
		} else {
			start = 0;
			limit = 2;
		}
		List<MerchantProduct> hotProducts = merchantProductService.findHotProducts(appDesc, start, limit);
		if (Utility.isNullOrEmpty(hotProducts)) {
			return null;
		}
		List<LoanProductsDto> popularRecommend = new ArrayList<>();
		for (MerchantProduct hotProduct : hotProducts) {
			SpeedloanHotProductDto sp = this.getHotProductDto(cust, accessToken, hotProduct);
			LoanProductsDto loanProductsDto = new LoanProductsDto();
			popularRecommend.add(loanProductsDto(loanProductsDto, sp));
		}
		return popularRecommend;
	}
}
